<?php
/**
 * Class for performing basic authentication functionality.
 * (login/logout/check status)
 * 
 * @package adroit
 */
class AdroitAuthenticator {
    
	/**
	 * @var String Identity column used for authorization
	 */
	private $identity;
	
	/**
	 * @var String Key column used for authentication
	 */
	private $key;
	
	/**
	 * @var String Name of class of Authentication object, defaults to User
	 */
	private $authClass;
	
    /**
     * @var Array Data stored to return to Model
     */
    private $data = Array();
    
    /**
     * Constructor
     *
     * @param Array $requestData Request(GET/POST) data
     * @return Authenticator
     */
    public function AdroitAuthenticator($authClass='User', $identity='email', $key='password') {
        $this->authClass = $authClass;
        $this->identity = $identity;
        $this->key = $key;
    }
    
    /**
     * Main entry point into Authenticator.
     * Performs login/logout/check status functionality depending on the 'action' string
     * $action may equal 'login', 'logout', or '' will perform a login status check
     *
     * @return mised Returns a boolean indicating what occured, or possibly a User object if authenticated
     */
    public function process($action='', $identityValue, $keyValue, $remember=true) {
        switch($action) {
            case 'login' :
                return $this->login($identityValue, $keyValue, $remember);
                break;
            case 'logout' :
                return $this->logout();
                break;
            default :
                return $this->checkLoginStatus();
                break;
        }
    }
    
    /**
     * Updates session User object and cookie if it's set
     *
     * @param User $user
     */
    public function updateSession(Authenticate $auth) {
		$auth->storeInSession();
        $cookieValue = @$_COOKIE['adroit_remember'];
        if($cookieValue != null && $this->verifyCookieValue($cookieValue)) {
            $this->setCookieValues($auth);
        }
    }
    
    /**
     * Performs login functionality.
     */
    public function login($identityValue, $keyValue, $remember) {
        $loginData[$this->identity] = $identityValue;
        $loginData[$this->key] = $keyValue;
        $class = $this->authClass;
        $auth = new $class($loginData);
        $validatedAuth = $auth->authenticate();
        if(!$validatedAuth) {
            Adroit::$alerts->addAlert('Invalid username and/or password', AdroitAlertHandler::$TYPE_ERROR);
            return false;
        }else {
        	$validatedAuth->storeInSession();
            if($remember) {
                $this->setCookieValues($validatedAuth);
            }
			return $validatedAuth;
        }
    }

    /**
     * Performs logout functionality.
     */
    public function logout() {
        session_destroy();
        if(@isset($_COOKIE['adroit_remember'])) {
            setcookie('adroit_remember', '', time()-2592000, '/', false);
        }
        return false;
    }

    /**
     * Checks the status of the current user(logged in or not)
     */
    public function checkLoginStatus() {
        $class = new ReflectionClass($this->authClass);
        $auth = $class->getMethod('getFromSession')->invoke(Array());
		if(@$auth->id != null) {
		    return $auth;
		}else {
            /* Check cookie for login credentials */
            $cookieValue = @$_COOKIE['adroit_remember'];
            if($cookieValue != null && $this->verifyCookieValue($cookieValue)) {
                return $auth;
            }else {
                return false;
            }
        }
    }

    /**
     * Creates a cookie with parameters to auto-login user upon return.
     */
    private function setCookieValues(Authenticate $auth) {
        $identity = $this->identity;
        $key = $this->key;
        setcookie('adroit_remember',
        $auth->id . '|' . md5($auth->$identity . $auth->$key),
        time()+2592000, '/', false);
    }

    /**
     * Validates the authenticity of a cookie
     */
    private function verifyCookieValue($value) {
        $cookieInfo = explode('|', $value);
        $identity_id = $cookieInfo[0];
        $hashCheck = $cookieInfo[1];
        $class = new ReflectionClass($this->authClass);
        $auth = $class->getMethod('validateCookie')->invokeArgs($class, Array($identity_id, $hashCheck));
        if($auth != false) {
            $auth->storeInSession();
            return true;
        }else {
            return false;
        }
    }
    
}
?>